import { defaultToString, ValuePair, IMap } from "../types";

export default class Dictionary<K, V> implements IMap<K, V> {
  private table: { [key: string]: ValuePair<K, V> };
  constructor(private toStrFn: (key: K) => string = defaultToString) {
    this.table = {};
  }

  /**判断字典中是否包含某个key
   *
   * @param key
   * @returns
   */
  public hasKey(key: K): boolean {
    return this.table[this.toStrFn(key)] != null;
  }

  /**向字典中添加元素
   *
   * @param key
   * @param value
   * @returns
   */
  public set(key: K, value: V): boolean {
    if (key != null && value != null) {
      const tableKey = this.toStrFn(key);
      this.table[tableKey] = new ValuePair(key, value);
      return true;
    }
    return false;
  }

  /** 从字典中移除一个值
   *
   * @param key
   * @returns
   */
  public remove(key: K): boolean {
    if (this.hasKey(key)) {
      delete this.table[this.toStrFn(key)];
      return true;
    }
    return false;
  }

  /**从字典中获取一个值
   *
   * @param key
   * @returns
   */
  public get(key: K): V | undefined {
    const valuePair = this.table[this.toStrFn(key)];
    return valuePair == null ? undefined : valuePair.value;
  }

  /**获取字典中存储的所有对象
   *
   * @returns
   */
  public keyValues(): ValuePair<K, V>[] {
    const valuePairs: ValuePair<K, V>[] = [];
    const keys = Object.keys(this.table);
    for (let i = 0; i < keys.length; i++) {
      valuePairs.push(this.table[keys[i]]);
    }
    return valuePairs!;
  }

  /**获取字典中的所有键
   *
   * @returns
   */
  public keys(): K[] {
    // 可以直接使用map获取对象的key
    // return this.keyValues().map(valuePair=> valuePair.key);
    const keys: K[] = [];
    const valuePairs = this.keyValues();
    for (let i = 0; i < valuePairs.length; i++) {
      keys.push(valuePairs[i].key);
    }
    return keys;
  }

  /**获取字典中的所有值
   *
   * @returns
   */
  public values(): V[] {
    const values: V[] = [];
    const valuePairs = this.keyValues();
    for (let i = 0; i < valuePairs.length; i++) {
      values.push(valuePairs[i].value);
    }
    return values;
  }

  /**迭代字典中的每个键值对
   *
   * @param callbackFn
   */
  public forEach(callbackFn: (key: K, value: V) => any): void {
    const valuePairs = this.keyValues();
    for (let i = 0; i < valuePairs.length; i++) {
      // 调用回调函数，传入key和value
      const result = callbackFn(valuePairs[i].key, valuePairs[i].value);
      // 如果回调函数返回false，则跳出循环
      if (result === false) {
        break;
      }
    }
  }

  /**字典中元素的数量
   *
   * @returns
   */
  public size(): number {
    return this.keyValues().length;
  }

  /**是否为空
   *
   * @returns
   */
  public isEmpty(): boolean {
    return this.size() === 0;
  }

  /**清除字典
   *
   */
  public clear(): void {
    this.table = {};
  }

  /**将字典中的数据转为字符串
   *
   * @returns
   */
  public toStr(): string {
    if (this.isEmpty()) {
      return "";
    }

    const valuePairs = this.keyValues();
    let objString = `${valuePairs[0].toString()}`;
    for (let i = 1; i < valuePairs.length; i++) {
      objString = `${objString},${valuePairs[i].toString()}`;
    }
    return objString;
  }
}
